home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / nt / emacssrc.zip / EMACSSRC.TAR / emacs-19.17 / src / vmsgmalloc.c < prev    next >
C/C++ Source or Header  |  1993-07-23  |  58KB  |  2,011 lines

  1. /* DO NOT EDIT THIS FILE -- it is automagically generated.  -*- C -*- */
  2.  
  3. #define _MALLOC_INTERNAL
  4.  
  5. /* The malloc headers and source files from the C library follow here.  */
  6.  
  7. /* Declarations for `malloc' and friends.
  8.    Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
  9.           Written May 1989 by Mike Haertel.
  10.  
  11. This library is free software; you can redistribute it and/or
  12. modify it under the terms of the GNU Library General Public License as
  13. published by the Free Software Foundation; either version 2 of the
  14. License, or (at your option) any later version.
  15.  
  16. This library is distributed in the hope that it will be useful,
  17. but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  19. Library General Public License for more details.
  20.  
  21. You should have received a copy of the GNU Library General Public
  22. License along with this library; see the file COPYING.LIB.  If
  23. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  24. Cambridge, MA 02139, USA.
  25.  
  26.    The author may be reached (Email) at the address mike@ai.mit.edu,
  27.    or (US mail) as Mike Haertel c/o Free Software Foundation.  */
  28.  
  29. #ifndef _MALLOC_H
  30.  
  31. #define _MALLOC_H    1
  32.  
  33. #ifdef    __cplusplus
  34. extern "C"
  35. {
  36. #endif
  37.  
  38. #if defined (__cplusplus) || (defined (__STDC__) && __STDC__)
  39. #undef    __P
  40. #define    __P(args)    args
  41. #undef  __const
  42. #define __const        const
  43. #undef    __ptr_t
  44. #define    __ptr_t        void *
  45. #else /* Not C++ or ANSI C.  */
  46. #undef    __P
  47. #define    __P(args)    ()
  48. #undef    __const
  49. #define    __const
  50. #undef    __ptr_t
  51. #define    __ptr_t        char *
  52. #endif /* C++ or ANSI C.  */
  53.  
  54. #ifndef    NULL
  55. #define    NULL    0
  56. #endif
  57.  
  58. #ifdef    __STDC__
  59. #include <stddef.h>
  60. #else
  61. #ifdef VMS /* The following are defined in stdio.h, but we need it NOW!
  62.           But do NOT do it with defines here, for then, VAX C is going
  63.           to barf when it gets to stdio.h and the typedefs in there! */
  64. typedef unsigned int size_t;
  65. typedef int ptrdiff_t;
  66. #else /* not VMS */
  67. #undef    size_t
  68. #define    size_t        unsigned int
  69. #undef    ptrdiff_t
  70. #define    ptrdiff_t    int
  71. #endif /* VMS */
  72. #endif
  73.  
  74.  
  75. /* Allocate SIZE bytes of memory.  */
  76. extern __ptr_t malloc __P ((size_t __size));
  77. /* Re-allocate the previously allocated block
  78.    in __ptr_t, making the new block SIZE bytes long.  */
  79. extern __ptr_t realloc __P ((__ptr_t __ptr, size_t __size));
  80. /* Allocate NMEMB elements of SIZE bytes each, all initialized to 0.  */
  81. extern __ptr_t calloc __P ((size_t __nmemb, size_t __size));
  82. /* Free a block allocated by `malloc', `realloc' or `calloc'.  */
  83. extern void free __P ((__ptr_t __ptr));
  84.  
  85. /* Allocate SIZE bytes allocated to ALIGNMENT bytes.  */
  86. extern __ptr_t memalign __P ((size_t __alignment, size_t __size));
  87.  
  88. /* Allocate SIZE bytes on a page boundary.  */
  89. extern __ptr_t valloc __P ((size_t __size));
  90.  
  91. #ifdef VMS
  92. /* VMS hooks to deal with two heaps */
  93. /* Allocate SIZE bytes of memory.  */
  94. extern __ptr_t __vms_malloc __P ((size_t __size));
  95. /* Re-allocate the previously allocated block
  96.    in __ptr_t, making the new block SIZE bytes long.  */
  97. extern __ptr_t __vms_realloc __P ((__ptr_t __ptr, size_t __size));
  98. /* Free a block allocated by `malloc', `realloc' or `calloc'.  */
  99. extern void __vms_free __P ((__ptr_t __ptr));
  100. #endif
  101.  
  102. #ifdef _MALLOC_INTERNAL
  103.  
  104. #include <stdio.h>        /* Harmless, gets __GNU_LIBRARY__ defined.  */
  105.  
  106. #if defined(HAVE_CONFIG_H) || defined(emacs)
  107. #include "config.h"
  108. #endif
  109.  
  110. #if    defined(__GNU_LIBRARY__) || defined(STDC_HEADERS) || defined(USG)
  111. #include <string.h>
  112. #else
  113. #ifndef memset
  114. #define    memset(s, zero, n)    bzero ((s), (n))
  115. #endif
  116. #ifndef memcpy
  117. #define    memcpy(d, s, n)        bcopy ((s), (d), (n))
  118. #endif
  119. #ifndef memmove
  120. #define    memmove(d, s, n)    bcopy ((s), (d), (n))
  121. #endif
  122. #endif
  123.  
  124.  
  125. #if    defined(__GNU_LIBRARY__) || defined(__STDC__)
  126. #include <limits.h>
  127. #else
  128. #define    CHAR_BIT    8
  129. #endif
  130.  
  131. /* The allocator divides the heap into blocks of fixed size; large
  132.    requests receive one or more whole blocks, and small requests
  133.    receive a fragment of a block.  Fragment sizes are powers of two,
  134.    and all fragments of a block are the same size.  When all the
  135.    fragments in a block have been freed, the block itself is freed.  */
  136. #define INT_BIT        (CHAR_BIT * sizeof(int))
  137. #ifdef VMS
  138. #define BLOCKLOG    9
  139. #else
  140. #define BLOCKLOG    (INT_BIT > 16 ? 12 : 9)
  141. #endif
  142. #define BLOCKSIZE    (1 << BLOCKLOG)
  143. #define BLOCKIFY(SIZE)    (((SIZE) + BLOCKSIZE - 1) / BLOCKSIZE)
  144.  
  145. /* Determine the amount of memory spanned by the initial heap table
  146.    (not an absolute limit).  */
  147. #define HEAP        (INT_BIT > 16 ? 4194304 : 65536)
  148.  
  149. /* Number of contiguous free blocks allowed to build up at the end of
  150.    memory before they will be returned to the system.  */
  151. #define FINAL_FREE_BLOCKS    8
  152.  
  153. /* Data structure giving per-block information.  */
  154. typedef union
  155.   {
  156.     /* Heap information for a busy block.  */
  157.     struct
  158.       {
  159.     /* Zero for a large block, or positive giving the
  160.        logarithm to the base two of the fragment size.  */
  161.     int type;
  162.     union
  163.       {
  164.         struct
  165.           {
  166.         size_t nfree;    /* Free fragments in a fragmented block.  */
  167.         size_t first;    /* First free fragment of the block.  */
  168.           } frag;
  169.         /* Size (in blocks) of a large cluster.  */
  170.         size_t size;
  171.       } info;
  172.       } busy;
  173.     /* Heap information for a free block
  174.        (that may be the first of a free cluster).  */
  175.     struct
  176.       {
  177.     size_t size;        /* Size (in blocks) of a free cluster.  */
  178.     size_t next;        /* Index of next free cluster.  */
  179.     size_t prev;        /* Index of previous free cluster.  */
  180.       } free;
  181.   } malloc_info;
  182.  
  183. /* Pointer to first block of the heap.  */
  184. extern char *_heapbase;
  185.  
  186. /* Table indexed by block number giving per-block information.  */
  187. extern malloc_info *_heapinfo;
  188.  
  189. /* Address to block number and vice versa.  */
  190. #define BLOCK(A)    (((char *) (A) - _heapbase) / BLOCKSIZE + 1)
  191. #define ADDRESS(B)    ((__ptr_t) (((B) - 1) * BLOCKSIZE + _heapbase))
  192.  
  193. /* Current search index for the heap table.  */
  194. extern size_t _heapindex;
  195.  
  196. /* Limit of valid info table indices.  */
  197. extern size_t _heaplimit;
  198.  
  199. /* Doubly linked lists of free fragments.  */
  200. struct list
  201.   {
  202.     struct list *next;
  203.     struct list *prev;
  204.   };
  205.  
  206. /* Free list headers for each fragment size.  */
  207. extern struct list _fraghead[];
  208.  
  209. /* List of blocks allocated with `memalign' (or `valloc').  */
  210. struct alignlist
  211.   {
  212.     struct alignlist *next;
  213.     __ptr_t aligned;        /* The address that memaligned returned.  */
  214.     __ptr_t exact;        /* The address that malloc returned.  */
  215.   };
  216. extern struct alignlist *_aligned_blocks;
  217.  
  218. /* Instrumentation.  */
  219. extern size_t _chunks_used;
  220. extern size_t _bytes_used;
  221. extern size_t _chunks_free;
  222. extern size_t _bytes_free;
  223.  
  224. /* Internal version of `free' used in `morecore' (malloc.c). */
  225. extern void _free_internal __P ((__ptr_t __ptr));
  226.  
  227. #endif /* _MALLOC_INTERNAL.  */
  228.  
  229. /* Underlying allocation function; successive calls should
  230.    return contiguous pieces of memory.  */
  231. /* It does NOT always return contiguous pieces of memory on VMS. */
  232. extern __ptr_t (*__morecore) __P ((ptrdiff_t __size));
  233.  
  234. /* Underlying deallocation function. It accepts both a pointer and
  235.    a size to back up. It is implementation dependent what is really
  236.    used. */
  237. extern __ptr_t (*__lesscore) __P ((__ptr_t __ptr, ptrdiff_t __size));
  238.  
  239. /* Default value of `__morecore'.  */
  240. extern __ptr_t __default_morecore __P ((ptrdiff_t __size));
  241.  
  242. /* Default value of `__lesscore'.  */
  243. extern __ptr_t __default_lesscore __P ((__ptr_t __ptr, ptrdiff_t __size));
  244.  
  245. #ifdef VMS
  246. /* Default value of `__morecore'.  */
  247. extern __ptr_t __vms_morecore __P ((ptrdiff_t __size));
  248.  
  249. /* Default value of `__lesscore'.  */
  250. extern __ptr_t __vms_lesscore __P ((__ptr_t __ptr, ptrdiff_t __size));
  251. #endif
  252.  
  253. /* If not NULL, this function is called after each time
  254.    `__morecore' is called to increase the data size.  */
  255. extern void (*__after_morecore_hook) __P ((void));
  256.  
  257. /* If not NULL, this function is called after each time
  258.    `__lesscore' is called to increase the data size.  */
  259. extern void (*__after_lesscore_hook) __P ((void));
  260.  
  261. /* Nonzero if `malloc' has been called and done its initialization.  */
  262. extern int __malloc_initialized;
  263.  
  264. /* Hooks for debugging versions.  */
  265. extern void (*__free_hook) __P ((__ptr_t __ptr));
  266. extern __ptr_t (*__malloc_hook) __P ((size_t __size));
  267. extern __ptr_t (*__realloc_hook) __P ((__ptr_t __ptr, size_t __size));
  268.  
  269. /* Activate a standard collection of debugging hooks.  */
  270. extern int mcheck __P ((void (*__func) __P ((void))));
  271.  
  272. /* Activate a standard collection of tracing hooks.  */
  273. extern void mtrace __P ((void));
  274.  
  275. /* Statistics available to the user.  */
  276. struct mstats
  277.   {
  278.     size_t bytes_total;        /* Total size of the heap. */
  279.     size_t chunks_used;        /* Chunks allocated by the user. */
  280.     size_t bytes_used;        /* Byte total of user-allocated chunks. */
  281.     size_t chunks_free;        /* Chunks in the free list. */
  282.     size_t bytes_free;        /* Byte total of chunks in the free list. */
  283.   };
  284.  
  285. /* Pick up the current statistics. */
  286. extern struct mstats mstats __P ((void));
  287.  
  288. /* Call WARNFUN with a warning message when memory usage is high.  */
  289. extern void memory_warnings __P ((__ptr_t __start,
  290.                   void (*__warnfun) __P ((__const char *))));
  291.  
  292.  
  293. /* Relocating allocator.  */
  294.  
  295. /* Allocate SIZE bytes, and store the address in *HANDLEPTR.  */
  296. extern __ptr_t r_alloc __P ((__ptr_t *__handleptr, size_t __size));
  297.  
  298. /* Free the storage allocated in HANDLEPTR.  */
  299. extern void r_alloc_free __P ((__ptr_t *__handleptr));
  300.  
  301. /* Adjust the block at HANDLEPTR to be SIZE bytes long.  */
  302. extern __ptr_t r_re_alloc __P ((__ptr_t *__handleptr, size_t __size));
  303.  
  304.  
  305. #ifdef    __cplusplus
  306. }
  307. #endif
  308.  
  309. #endif /* malloc.h  */
  310. /* Memory allocator `malloc'.
  311.    Copyright 1990, 1991, 1992, 1993 Free Software Foundation
  312.           Written May 1989 by Mike Haertel.
  313.  
  314. This library is free software; you can redistribute it and/or
  315. modify it under the terms of the GNU Library General Public License as
  316. published by the Free Software Foundation; either version 2 of the
  317. License, or (at your option) any later version.
  318.  
  319. This library is distributed in the hope that it will be useful,
  320. but WITHOUT ANY WARRANTY; without even the implied warranty of
  321. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  322. Library General Public License for more details.
  323.  
  324. You should have received a copy of the GNU Library General Public
  325. License along with this library; see the file COPYING.LIB.  If
  326. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  327. Cambridge, MA 02139, USA.
  328.  
  329.    The author may be reached (Email) at the address mike@ai.mit.edu,
  330.    or (US mail) as Mike Haertel c/o Free Software Foundation.  */
  331.  
  332. #ifndef    _MALLOC_INTERNAL
  333. #define _MALLOC_INTERNAL
  334. #include <malloc.h>
  335. #endif
  336.  
  337. #ifdef VMS
  338. /* How to really get more memory.  */
  339. __ptr_t (*__morecore) __P ((ptrdiff_t __size)) = __vms_morecore;
  340. #else
  341. /* How to really get more memory.  */
  342. __ptr_t (*__morecore) __P ((ptrdiff_t __size)) = __default_morecore;
  343. #endif
  344.  
  345. /* Debugging hook for `malloc'.  */
  346. #ifdef VMS
  347. __ptr_t (*__malloc_hook) __P ((size_t __size)) = __vms_malloc;
  348. #else
  349. __ptr_t (*__malloc_hook) __P ((size_t __size));
  350. #endif
  351.  
  352. /* Pointer to the base of the first block.  */
  353. char *_heapbase;
  354.  
  355. /* Block information table.  Allocated with align/__free (not malloc/free).  */
  356. malloc_info *_heapinfo;
  357.  
  358. /* Number of info entries.  */
  359. static size_t heapsize;
  360.  
  361. /* Search index in the info table.  */
  362. size_t _heapindex;
  363.  
  364. /* Limit of valid info table indices.  */
  365. size_t _heaplimit;
  366.  
  367. /* Free lists for each fragment size.  */
  368. struct list _fraghead[BLOCKLOG];
  369.  
  370. /* Instrumentation.  */
  371. size_t _chunks_used;
  372. size_t _bytes_used;
  373. size_t _chunks_free;
  374. size_t _bytes_free;
  375.  
  376. /* Are you experienced?  */
  377. int __malloc_initialized;
  378.  
  379. void (*__after_morecore_hook) __P ((void));
  380.  
  381. /* Aligned allocation.  */
  382. static __ptr_t align __P ((size_t));
  383. static __ptr_t
  384. align (size)
  385.      size_t size;
  386. {
  387.   __ptr_t result;
  388.   unsigned long int adj;
  389.  
  390.   result = (*__morecore) (size);
  391.   adj = (unsigned long int) ((unsigned long int) ((char *) result -
  392.                         (char *) NULL)) % BLOCKSIZE;
  393.   if (adj != 0)
  394.     {
  395.       adj = BLOCKSIZE - adj;
  396.       (void) (*__morecore) (adj);
  397.       result = (char *) result + adj;
  398.     }
  399.  
  400.   if (__after_morecore_hook)
  401.     (*__after_morecore_hook) ();
  402.  
  403.   return result;
  404. }
  405.  
  406. /* Set everything up and remember that we have.  */
  407. static int initialize __P ((void));
  408. static int
  409. initialize ()
  410. {
  411. #ifdef RL_DEBUG
  412.   extern VMS_present_buffer();
  413.   printf("__malloc_initialized = %d\n", __malloc_initialized);
  414.   VMS_present_buffer();
  415. #endif
  416.   heapsize = HEAP / BLOCKSIZE;
  417.   _heapinfo = (malloc_info *) align (heapsize * sizeof (malloc_info));
  418.   if (_heapinfo == NULL)
  419.     return 0;
  420.   memset (_heapinfo, 0, heapsize * sizeof (malloc_info));
  421.   _heapinfo[0].free.size = 0;
  422.   _heapinfo[0].free.next = _heapinfo[0].free.prev = 0;
  423.   _heapindex = 0;
  424.   _heapbase = (char *) _heapinfo;
  425. #ifdef RL_DEBUG
  426. /* debug */
  427.   printf("_heapbase = 0%o/0x%x/%d\n", _heapbase, _heapbase, _heapbase);
  428. /* end debug */
  429. #endif
  430.   __malloc_initialized = 1;
  431.   return 1;
  432. }
  433.  
  434. /* Get neatly aligned memory, initializing or
  435.    growing the heap info table as necessary. */
  436. static __ptr_t morecore __P ((size_t));
  437. static __ptr_t
  438. morecore (size)
  439.      size_t size;
  440. {
  441.   __ptr_t result;
  442.   malloc_info *newinfo, *oldinfo;
  443.   size_t newsize;
  444.  
  445.   result = align (size);
  446.   if (result == NULL)
  447.     return NULL;
  448.  
  449.   /* Check if we need to grow the info table.  */
  450.   if ((size_t) BLOCK ((char *) result + size) > heapsize)
  451.     {
  452.       newsize = heapsize;
  453.       while ((size_t) BLOCK ((char *) result + size) > newsize)
  454.     newsize *= 2;
  455.       newinfo = (malloc_info *) align (newsize * sizeof (malloc_info));
  456.       if (newinfo == NULL)
  457.     {
  458.       (*__lesscore) (result, size);
  459.       return NULL;
  460.     }
  461.       memset (newinfo, 0, newsize * sizeof (malloc_info));
  462.       memcpy (newinfo, _heapinfo, heapsize * sizeof (malloc_info));
  463.       oldinfo = _heapinfo;
  464.       newinfo[BLOCK (oldinfo)].busy.type = 0;
  465.       newinfo[BLOCK (oldinfo)].busy.info.size
  466.     = BLOCKIFY (heapsize * sizeof (malloc_info));
  467.       _heapinfo = newinfo;
  468.       _free_internal (oldinfo);
  469.       heapsize = newsize;
  470.     }
  471.  
  472.   _heaplimit = BLOCK ((char *) result + size);
  473.   return result;
  474. }
  475.  
  476. /* Allocate memory from the heap.  */
  477. __ptr_t
  478. malloc (size)
  479.      size_t size;
  480. {
  481.   __ptr_t result;
  482.   size_t block, blocks, lastblocks, start;
  483.   register size_t i;
  484.   struct list *next;
  485.  
  486.   if (size == 0)
  487.     return NULL;
  488.  
  489.   if (__malloc_hook != NULL)
  490.     return (*__malloc_hook) (size);
  491.  
  492.   if (!__malloc_initialized)
  493.     if (!initialize ())
  494.       return NULL;
  495.  
  496.   if (size < sizeof (struct list))
  497.       size = sizeof (struct list);
  498.  
  499.   /* Determine the allocation policy based on the request size.  */
  500.   if (size <= BLOCKSIZE / 2)
  501.     {
  502.       /* Small allocation to receive a fragment of a block.
  503.      Determine the logarithm to base two of the fragment size. */
  504.       register size_t log = 1;
  505.       --size;
  506.       while ((size /= 2) != 0)
  507.     ++log;
  508.  
  509.       /* Look in the fragment lists for a
  510.      free fragment of the desired size. */
  511.       next = _fraghead[log].next;
  512.       if (next != NULL)
  513.     {
  514.       /* There are free fragments of this size.
  515.          Pop a fragment out of the fragment list and return it.
  516.          Update the block's nfree and first counters. */
  517.       result = (__ptr_t) next;
  518.       next->prev->next = next->next;
  519.       if (next->next != NULL)
  520.         next->next->prev = next->prev;
  521.       block = BLOCK (result);
  522.       if (--_heapinfo[block].busy.info.frag.nfree != 0)
  523.         _heapinfo[block].busy.info.frag.first = (unsigned long int)
  524.           ((unsigned long int) ((char *) next->next - (char *) NULL)
  525.            % BLOCKSIZE) >> log;
  526.  
  527.       /* Update the statistics.  */
  528.       ++_chunks_used;
  529.       _bytes_used += 1 << log;
  530.       --_chunks_free;
  531.       _bytes_free -= 1 << log;
  532.     }
  533.       else
  534.     {
  535.       /* No free fragments of the desired size, so get a new block
  536.          and break it into fragments, returning the first.  */
  537.       result = malloc (BLOCKSIZE);
  538.       if (result == NULL)
  539.         return NULL;
  540.  
  541.       /* Link all fragments but the first into the free list.  */
  542.       for (i = 1; i < (size_t) (BLOCKSIZE >> log); ++i)
  543.         {
  544.           next = (struct list *) ((char *) result + (i << log));
  545. #ifdef RL_DEBUG
  546.           printf("DEBUG:  malloc (%d): next = %p\n", size, next);
  547. #endif
  548.           next->next = _fraghead[log].next;
  549.           next->prev = &_fraghead[log];
  550.           next->prev->next = next;
  551.           if (next->next != NULL)
  552.         next->next->prev = next;
  553.         }
  554.  
  555.       /* Initialize the nfree and first counters for this block.  */
  556.       block = BLOCK (result);
  557.       _heapinfo[block].busy.type = log;
  558.       _heapinfo[block].busy.info.frag.nfree = i - 1;
  559.       _heapinfo[block].busy.info.frag.first = i - 1;
  560.  
  561.       _chunks_free += (BLOCKSIZE >> log) - 1;
  562.       _bytes_free += BLOCKSIZE - (1 << log);
  563.       _bytes_used -= BLOCKSIZE - (1 << log);
  564.     }
  565.     }
  566.   else
  567.     {
  568.       /* Large allocation to receive one or more blocks.
  569.      Search the free list in a circle starting at the last place visited.
  570.      If we loop completely around without finding a large enough
  571.      space we will have to get more memory from the system.  */
  572.       blocks = BLOCKIFY (size);
  573.       start = block = _heapindex;
  574.       while (_heapinfo[block].free.size < blocks)
  575.     {
  576.       block = _heapinfo[block].free.next;
  577.       if (block == start)
  578.         {
  579.           /* Need to get more from the system.  Check to see if
  580.          the new core will be contiguous with the final free
  581.          block; if so we don't need to get as much.  */
  582.           block = _heapinfo[0].free.prev;
  583.           lastblocks = _heapinfo[block].free.size;
  584.           if (_heaplimit != 0 && block + lastblocks == _heaplimit &&
  585.           (*__morecore) (0) == ADDRESS (block + lastblocks) &&
  586.           (morecore ((blocks - lastblocks) * BLOCKSIZE)) != NULL)
  587.         {
  588.           _heapinfo[block].free.size = blocks;
  589.           _bytes_free += (blocks - lastblocks) * BLOCKSIZE;
  590.           continue;
  591.         }
  592.           result = morecore (blocks * BLOCKSIZE);
  593.           if (result == NULL)
  594.         return NULL;
  595.           block = BLOCK (result);
  596.           _heapinfo[block].busy.type = 0;
  597.           _heapinfo[block].busy.info.size = blocks;
  598.           ++_chunks_used;
  599.           _bytes_used += blocks * BLOCKSIZE;
  600.           return result;
  601.         }
  602.     }
  603.  
  604.       /* At this point we have found a suitable free list entry.
  605.      Figure out how to remove what we need from the list. */
  606.       result = ADDRESS (block);
  607.       if (_heapinfo[block].free.size > blocks)
  608.     {
  609.       /* The block we found has a bit left over,
  610.          so relink the tail end back into the free list. */
  611.       _heapinfo[block + blocks].free.size
  612.         = _heapinfo[block].free.size - blocks;
  613.       _heapinfo[block + blocks].free.next
  614.         = _heapinfo[block].free.next;
  615.       _heapinfo[block + blocks].free.prev
  616.         = _heapinfo[block].free.prev;
  617.       _heapinfo[_heapinfo[block].free.prev].free.next
  618.         = _heapinfo[_heapinfo[block].free.next].free.prev
  619.         = _heapindex = block + blocks;
  620.     }
  621.       else
  622.     {
  623.       /* The block exactly matches our requirements,
  624.          so just remove it from the list. */
  625.       _heapinfo[_heapinfo[block].free.next].free.prev
  626.         = _heapinfo[block].free.prev;
  627.       _heapinfo[_heapinfo[block].free.prev].free.next
  628.         = _heapindex = _heapinfo[block].free.next;
  629.       --_chunks_free;
  630.     }
  631.  
  632.       _heapinfo[block].busy.type = 0;
  633.       _heapinfo[block].busy.info.size = blocks;
  634.       ++_chunks_used;
  635.       _bytes_used += blocks * BLOCKSIZE;
  636.       _bytes_free -= blocks * BLOCKSIZE;
  637.     }
  638.  
  639.   return result;
  640. }
  641. /* Free a block of memory allocated by `malloc'.
  642.    Copyright 1990, 1991, 1992 Free Software Foundation
  643.           Written May 1989 by Mike Haertel.
  644.  
  645. This library is free software; you can redistribute it and/or
  646. modify it under the terms of the GNU Library General Public License as
  647. published by the Free Software Foundation; either version 2 of the
  648. License, or (at your option) any later version.
  649.  
  650. This library is distributed in the hope that it will be useful,
  651. but WITHOUT ANY WARRANTY; without even the implied warranty of
  652. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  653. Library General Public License for more details.
  654.  
  655. You should have received a copy of the GNU Library General Public
  656. License along with this library; see the file COPYING.LIB.  If
  657. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  658. Cambridge, MA 02139, USA.
  659.  
  660.    The author may be reached (Email) at the address mike@ai.mit.edu,
  661.    or (US mail) as Mike Haertel c/o Free Software Foundation.  */
  662.  
  663. #ifndef    _MALLOC_INTERNAL
  664. #define _MALLOC_INTERNAL
  665. #include <malloc.h>
  666. #endif
  667.  
  668. #ifdef VMS
  669. /* How to really get more memory.  */
  670. __ptr_t (*__lesscore) __P ((__ptr_t __ptr,ptrdiff_t __size)) = __vms_lesscore;
  671. #else
  672. /* How to really get more memory.  */
  673. __ptr_t (*__lesscore) __P ((__ptr_t __ptr,ptrdiff_t __size)) = __default_lesscore;
  674. #endif
  675.  
  676. /* Debugging hook for free.  */
  677. #ifdef VMS
  678. void (*__free_hook) __P ((__ptr_t __ptr)) = __vms_free;
  679. #else
  680. void (*__free_hook) __P ((__ptr_t __ptr));
  681. #endif
  682.  
  683. /* List of blocks allocated by memalign.  */
  684. struct alignlist *_aligned_blocks = NULL;
  685.  
  686. /* Return memory to the heap.
  687.    Like `free' but don't call a __free_hook if there is one.  */
  688. void
  689. _free_internal (ptr)
  690.      __ptr_t ptr;
  691. {
  692.   int type;
  693.   size_t block, blocks;
  694.   register size_t i;
  695.   struct list *prev, *next;
  696.  
  697.   block = BLOCK (ptr);
  698.  
  699.   type = _heapinfo[block].busy.type;
  700.   switch (type)
  701.     {
  702.     case 0:
  703.       /* Get as many statistics as early as we can.  */
  704.       --_chunks_used;
  705.       _bytes_used -= _heapinfo[block].busy.info.size * BLOCKSIZE;
  706.       _bytes_free += _heapinfo[block].busy.info.size * BLOCKSIZE;
  707.  
  708.       /* Find the free cluster previous to this one in the free list.
  709.      Start searching at the last block referenced; this may benefit
  710.      programs with locality of allocation.  */
  711.       i = _heapindex;
  712.       if (i > block)
  713.     while (i > block)
  714.       i = _heapinfo[i].free.prev;
  715.       else
  716.     {
  717.       do
  718.         i = _heapinfo[i].free.next;
  719.       while (i > 0 && i < block);
  720.       i = _heapinfo[i].free.prev;
  721.     }
  722.  
  723.       /* Determine how to link this block into the free list.  */
  724.       if (block == i + _heapinfo[i].free.size)
  725.     {
  726.       /* Coalesce this block with its predecessor.  */
  727.       _heapinfo[i].free.size += _heapinfo[block].busy.info.size;
  728.       block = i;
  729.     }
  730.       else
  731.     {
  732.       /* Really link this block back into the free list.  */
  733.       _heapinfo[block].free.size = _heapinfo[block].busy.info.size;
  734.       _heapinfo[block].free.next = _heapinfo[i].free.next;
  735.       _heapinfo[block].free.prev = i;
  736.       _heapinfo[i].free.next = block;
  737.       _heapinfo[_heapinfo[block].free.next].free.prev = block;
  738.       ++_chunks_free;
  739.     }
  740.  
  741.       /* Now that the block is linked in, see if we can coalesce it
  742.      with its successor (by deleting its successor from the list
  743.      and adding in its size).  */
  744.       if (block + _heapinfo[block].free.size == _heapinfo[block].free.next)
  745.     {
  746.       _heapinfo[block].free.size
  747.         += _heapinfo[_heapinfo[block].free.next].free.size;
  748.       _heapinfo[block].free.next
  749.         = _heapinfo[_heapinfo[block].free.next].free.next;
  750.       _heapinfo[_heapinfo[block].free.next].free.prev = block;
  751.       --_chunks_free;
  752.     }
  753.  
  754.       /* Now see if we can return stuff to the system.  */
  755.       blocks = _heapinfo[block].free.size;
  756.       if (blocks >= FINAL_FREE_BLOCKS && block + blocks == _heaplimit
  757.       && (*__morecore) (0) == ADDRESS (block + blocks))
  758.     {
  759.       register size_t bytes = blocks * BLOCKSIZE;
  760.       _heaplimit -= blocks;
  761.       (*__lesscore) (ADDRESS(block), bytes);
  762.       _heapinfo[_heapinfo[block].free.prev].free.next
  763.         = _heapinfo[block].free.next;
  764.       _heapinfo[_heapinfo[block].free.next].free.prev
  765.         = _heapinfo[block].free.prev;
  766.       block = _heapinfo[block].free.prev;
  767.       --_chunks_free;
  768.       _bytes_free -= bytes;
  769.     }
  770.  
  771.       /* Set the next search to begin at this block.  */
  772.       _heapindex = block;
  773.       break;
  774.  
  775.     default:
  776.       /* Do some of the statistics.  */
  777.       --_chunks_used;
  778.       _bytes_used -= 1 << type;
  779.       ++_chunks_free;
  780.       _bytes_free += 1 << type;
  781.  
  782.       /* Get the address of the first free fragment in this block.  */
  783.       prev = (struct list *) ((char *) ADDRESS (block) +
  784.                (_heapinfo[block].busy.info.frag.first << type));
  785. #ifdef RL_DEBUG
  786.       printf("_free_internal(0%o/0x%x/%d) :\n", ptr, ptr, ptr);
  787.       printf("  block = %d, type = %d, prev = 0%o/0x%x/%d\n",
  788.          block, type, prev, prev, prev);
  789.       printf("  _heapinfo[block=%d].busy.info.frag.nfree = %d\n",
  790.          block,
  791.          _heapinfo[block].busy.info.frag.nfree);
  792. #endif
  793.  
  794.       if (_heapinfo[block].busy.info.frag.nfree == (BLOCKSIZE >> type) - 1)
  795.     {
  796.       /* If all fragments of this block are free, remove them
  797.          from the fragment list and free the whole block.  */
  798.       next = prev;
  799.       for (i = 1; i < (size_t) (BLOCKSIZE >> type); ++i)
  800.         next = next->next;
  801.       prev->prev->next = next;
  802.       if (next != NULL)
  803.         next->prev = prev->prev;
  804.       _heapinfo[block].busy.type = 0;
  805.       _heapinfo[block].busy.info.size = 1;
  806.  
  807.       /* Keep the statistics accurate.  */
  808.       ++_chunks_used;
  809.       _bytes_used += BLOCKSIZE;
  810.       _chunks_free -= BLOCKSIZE >> type;
  811.       _bytes_free -= BLOCKSIZE;
  812.  
  813.       free (ADDRESS (block));
  814.     }
  815.       else if (_heapinfo[block].busy.info.frag.nfree != 0)
  816.     {
  817.       /* If some fragments of this block are free, link this
  818.          fragment into the fragment list after the first free
  819.          fragment of this block. */
  820. #ifdef RL_DEBUG
  821.       printf("There's a bug hiding here (%s:%d), so I will print some values\n", __FILE__, __LINE__);
  822. #endif
  823.       next = (struct list *) ptr;
  824. #ifdef RL_DEBUG
  825.       printf("    (struct list *)next (0%o / 0x%x / %d) ->\n", next, next, next);
  826.       printf("          next = 0%o / 0x%x / %d\n", next->next,next->next,next->next);
  827.       printf("          prev = 0%o / 0x%x / %d\n", next->prev,next->prev,next->prev);
  828.       printf("    (struct list *)prev (0%o / 0x%x / %d)->\n", prev, prev, prev);
  829.       printf("          next = 0%o / 0x%x / %d\n", prev->next,prev->next,prev->next);
  830.       printf("          prev = 0%o / 0x%x / %d\n", prev->prev,prev->prev,prev->prev);
  831. #endif
  832.       next->next = prev->next;
  833.       next->prev = prev;
  834.       prev->next = next;
  835.       if (next->next != NULL)
  836.         next->next->prev = next;
  837.       ++_heapinfo[block].busy.info.frag.nfree;
  838.     }
  839.       else
  840.     {
  841.       /* No fragments of this block are free, so link this
  842.          fragment into the fragment list and announce that
  843.          it is the first free fragment of this block. */
  844.       prev = (struct list *) ptr;
  845.       _heapinfo[block].busy.info.frag.nfree = 1;
  846.       _heapinfo[block].busy.info.frag.first = (unsigned long int)
  847.         ((unsigned long int) ((char *) ptr - (char *) NULL)
  848.          % BLOCKSIZE >> type);
  849.       prev->next = _fraghead[type].next;
  850.       prev->prev = &_fraghead[type];
  851.       prev->prev->next = prev;
  852.       if (prev->next != NULL)
  853.         prev->next->prev = prev;
  854.     }
  855.       break;
  856.     }
  857. }
  858.  
  859. /* Return memory to the heap.  */
  860. void
  861. free (ptr)
  862.      __ptr_t ptr;
  863. {
  864.   register struct alignlist *l;
  865.  
  866.   if (ptr == NULL)
  867.     return;
  868.  
  869.   for (l = _aligned_blocks; l != NULL; l = l->next)
  870.     if (l->aligned == ptr)
  871.       {
  872.     l->aligned = NULL;    /* Mark the slot in the list as free.  */
  873.     ptr = l->exact;
  874.     break;
  875.       }
  876.  
  877.   if (__free_hook != NULL)
  878.     (*__free_hook) (ptr);
  879.   else
  880.     _free_internal (ptr);
  881. }
  882. /* Change the size of a block allocated by `malloc'.
  883.    Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
  884.              Written May 1989 by Mike Haertel.
  885.  
  886. This library is free software; you can redistribute it and/or
  887. modify it under the terms of the GNU Library General Public License as
  888. published by the Free Software Foundation; either version 2 of the
  889. License, or (at your option) any later version.
  890.  
  891. This library is distributed in the hope that it will be useful,
  892. but WITHOUT ANY WARRANTY; without even the implied warranty of
  893. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  894. Library General Public License for more details.
  895.  
  896. You should have received a copy of the GNU Library General Public
  897. License along with this library; see the file COPYING.LIB.  If
  898. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  899. Cambridge, MA 02139, USA.
  900.  
  901.    The author may be reached (Email) at the address mike@ai.mit.edu,
  902.    or (US mail) as Mike Haertel c/o Free Software Foundation.  */
  903.  
  904. #ifndef    _MALLOC_INTERNAL
  905. #define _MALLOC_INTERNAL
  906. #include <malloc.h>
  907. #endif
  908.  
  909. #define min(A, B) ((A) < (B) ? (A) : (B))
  910.  
  911. /* Debugging hook for realloc.  */
  912. #ifdef VMS
  913. __ptr_t (*__realloc_hook) __P ((__ptr_t __ptr, size_t __size)) = __vms_realloc;
  914. #else
  915. __ptr_t (*__realloc_hook) __P ((__ptr_t __ptr, size_t __size));
  916. #endif
  917.  
  918. /* Resize the given region to the new size, returning a pointer
  919.    to the (possibly moved) region.  This is optimized for speed;
  920.    some benchmarks seem to indicate that greater compactness is
  921.    achieved by unconditionally allocating and copying to a
  922.    new region.  This module has incestuous knowledge of the
  923.    internals of both free and malloc. */
  924. __ptr_t
  925. realloc (ptr, size)
  926.      __ptr_t ptr;
  927.      size_t size;
  928. {
  929.   __ptr_t result;
  930.   int type;
  931.   size_t block, blocks, oldlimit;
  932.  
  933.   if (size == 0)
  934.     {
  935.       free (ptr);
  936.       return malloc (0);
  937.     }
  938.   else if (ptr == NULL)
  939.     return malloc (size);
  940.  
  941.   if (__realloc_hook != NULL)
  942.     return (*__realloc_hook) (ptr, size);
  943.  
  944.   block = BLOCK (ptr);
  945.  
  946.   type = _heapinfo[block].busy.type;
  947.   switch (type)
  948.     {
  949.     case 0:
  950.       /* Maybe reallocate a large block to a small fragment.  */
  951.       if (size <= BLOCKSIZE / 2)
  952.     {
  953.       result = malloc (size);
  954.       if (result != NULL)
  955.         {
  956.           memcpy (result, ptr, size);
  957.           free (ptr);
  958.           return result;
  959.         }
  960.     }
  961.  
  962.       /* The new size is a large allocation as well;
  963.      see if we can hold it in place. */
  964.       blocks = BLOCKIFY (size);
  965.       if (blocks < _heapinfo[block].busy.info.size)
  966.     {
  967.       /* The new size is smaller; return
  968.          excess memory to the free list. */
  969.       _heapinfo[block + blocks].busy.type = 0;
  970.       _heapinfo[block + blocks].busy.info.size
  971.         = _heapinfo[block].busy.info.size - blocks;
  972.       _heapinfo[block].busy.info.size = blocks;
  973.       free (ADDRESS (block + blocks));
  974.       result = ptr;
  975.     }
  976.       else if (blocks == _heapinfo[block].busy.info.size)
  977.     /* No size change necessary.  */
  978.     result = ptr;
  979.       else
  980.     {
  981.       /* Won't fit, so allocate a new region that will.
  982.          Free the old region first in case there is sufficient
  983.          adjacent free space to grow without moving. */
  984.       blocks = _heapinfo[block].busy.info.size;
  985.       /* Prevent free from actually returning memory to the system.  */
  986.       oldlimit = _heaplimit;
  987.       _heaplimit = 0;
  988.       free (ptr);
  989.       _heaplimit = oldlimit;
  990.       result = malloc (size);
  991.       if (result == NULL)
  992.         {
  993.           /* Now we're really in trouble.  We have to unfree
  994.          the thing we just freed.  Unfortunately it might
  995.          have been coalesced with its neighbors.  */
  996.           if (_heapindex == block)
  997.             (void) malloc (blocks * BLOCKSIZE);
  998.           else
  999.         {
  1000.           __ptr_t previous = malloc ((block - _heapindex) * BLOCKSIZE);
  1001.           (void) malloc (blocks * BLOCKSIZE);
  1002.           free (previous);
  1003.         }
  1004.           return NULL;
  1005.         }
  1006.       if (ptr != result)
  1007.         memmove (result, ptr, blocks * BLOCKSIZE);
  1008.     }
  1009.       break;
  1010.  
  1011.     default:
  1012.       /* Old size is a fragment; type is logarithm
  1013.      to base two of the fragment size.  */
  1014.       if (size > (size_t) (1 << (type - 1)) && size <= (size_t) (1 << type))
  1015.     /* The new size is the same kind of fragment.  */
  1016.     result = ptr;
  1017.       else
  1018.     {
  1019.       /* The new size is different; allocate a new space,
  1020.          and copy the lesser of the new size and the old. */
  1021.       result = malloc (size);
  1022.       if (result == NULL)
  1023.         return NULL;
  1024.       memcpy (result, ptr, min (size, (size_t) 1 << type));
  1025.       free (ptr);
  1026.     }
  1027.       break;
  1028.     }
  1029.  
  1030.   return result;
  1031. }
  1032. /* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
  1033.  
  1034. This library is free software; you can redistribute it and/or
  1035. modify it under the terms of the GNU Library General Public License as
  1036. published by the Free Software Foundation; either version 2 of the
  1037. License, or (at your option) any later version.
  1038.  
  1039. This library is distributed in the hope that it will be useful,
  1040. but WITHOUT ANY WARRANTY; without even the implied warranty of
  1041. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  1042. Library General Public License for more details.
  1043.  
  1044. You should have received a copy of the GNU Library General Public
  1045. License along with this library; see the file COPYING.LIB.  If
  1046. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  1047. Cambridge, MA 02139, USA.
  1048.  
  1049.    The author may be reached (Email) at the address mike@ai.mit.edu,
  1050.    or (US mail) as Mike Haertel c/o Free Software Foundation.  */
  1051.  
  1052. #ifndef    _MALLOC_INTERNAL
  1053. #define    _MALLOC_INTERNAL
  1054. #include <malloc.h>
  1055. #endif
  1056.  
  1057. /* Allocate an array of NMEMB elements each SIZE bytes long.
  1058.    The entire array is initialized to zeros.  */
  1059. __ptr_t
  1060. calloc (nmemb, size)
  1061.      register size_t nmemb;
  1062.      register size_t size;
  1063. {
  1064.   register __ptr_t result = malloc (nmemb * size);
  1065.  
  1066.   if (result != NULL)
  1067.     (void) memset (result, 0, nmemb * size);
  1068.  
  1069.   return result;
  1070. }
  1071. /* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
  1072. This file is part of the GNU C Library.
  1073.  
  1074. The GNU C Library is free software; you can redistribute it and/or modify
  1075. it under the terms of the GNU General Public License as published by
  1076. the Free Software Foundation; either version 2, or (at your option)
  1077. any later version.
  1078.  
  1079. The GNU C Library is distributed in the hope that it will be useful,
  1080. but WITHOUT ANY WARRANTY; without even the implied warranty of
  1081. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  1082. GNU General Public License for more details.
  1083.  
  1084. You should have received a copy of the GNU General Public License
  1085. along with the GNU C Library; see the file COPYING.  If not, write to
  1086. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  1087.  
  1088. #ifndef    _MALLOC_INTERNAL
  1089. #define    _MALLOC_INTERNAL
  1090. #include <malloc.h>
  1091. #endif
  1092.  
  1093. #ifndef    __GNU_LIBRARY__
  1094. #define    __sbrk    sbrk
  1095. #ifdef VMS
  1096. #define __brk brk
  1097. #endif
  1098. #endif
  1099.  
  1100. extern __ptr_t __sbrk __P ((int increment));
  1101.  
  1102. #ifndef NULL
  1103. #define NULL 0
  1104. #endif
  1105.  
  1106. #if defined(emacs) && defined(VMS)
  1107. /* Dumping of Emacs on VMS does not include the heap!
  1108.    So let's make a huge array from which initial data will be
  1109.    allocated.
  1110.  
  1111.    VMS_ALLOCATION_SIZE is the amount of memory we preallocate.
  1112.    We don't want it to be too large, because it only gives a larger
  1113.    dump file. The way to check how much is really used is to
  1114.    make VMS_ALLOCATION_SIZE very large, to link Emacs with the
  1115.    debugger, run Emacs, check how much was allocated. Then set
  1116.    VMS_ALLOCATION_SIZE to something suitable, recompile gmalloc,
  1117.    relink Emacs, and you should be off.
  1118.  
  1119.    N.B. This is experimental, but it worked quite fine on Emacs 18.
  1120. */
  1121. #ifndef VMS_ALLOCATION_SIZE
  1122. #define VMS_ALLOCATION_SIZE (512*(512+128))
  1123. #endif
  1124.  
  1125. int vms_out_initial = 0;
  1126. char vms_initial_buffer[VMS_ALLOCATION_SIZE];
  1127. char *vms_current_brk = vms_initial_buffer;
  1128. char *vms_end_brk = &vms_initial_buffer[VMS_ALLOCATION_SIZE-1];
  1129.  
  1130. __ptr_t
  1131. __vms_initial_morecore (increment)
  1132.      ptrdiff_t increment;
  1133. {
  1134.   __ptr_t result = NULL;
  1135.   __ptr_t temp;
  1136.  
  1137.   /* It's far easier to make the alignment here than to make a
  1138.      kludge in align () */
  1139. #ifdef RL_DEBUG
  1140.   printf(">>>foo... %p...", vms_current_brk);
  1141. #endif
  1142.   vms_current_brk += (BLOCKSIZE - ((unsigned long) vms_current_brk
  1143.                        & (BLOCKSIZE - 1))) & (BLOCKSIZE - 1);
  1144. #ifdef RL_DEBUG
  1145.   printf("bar... %p. (%d)\n", vms_current_brk, increment);
  1146. #endif
  1147.   temp = vms_current_brk + (int) increment;
  1148.   if (temp <= vms_end_brk)
  1149.     {
  1150.       if (increment >= 0)
  1151.     result = vms_current_brk;
  1152.       else
  1153.     result = temp;
  1154.       vms_current_brk = temp;
  1155.     }
  1156.   return result;
  1157. }
  1158.  
  1159. __ptr_t
  1160. __vms_initial_lesscore (ptr, size)
  1161.      __ptr_t ptr;
  1162.      ptrdiff_t size;
  1163. {
  1164.   if (ptr >= vms_initial_buffer
  1165.       && ptr < vms_initial_buffer+VMS_ALLOCATION_SIZE)
  1166.     {
  1167.       vms_current_brk = ptr;
  1168.       return vms_current_brk;
  1169.     }
  1170.   return vms_current_brk;
  1171. }
  1172.  
  1173. VMS_present_buffer()
  1174. {
  1175.   printf("Vms initial buffer starts at 0%o/0x%x/%d and ends at 0%o/0x%x/%d\n",
  1176.      vms_initial_buffer, vms_initial_buffer, vms_initial_buffer, 
  1177.      vms_end_brk, vms_end_brk, vms_end_brk);
  1178. }
  1179. #endif /* defined(emacs) && defined(VMS) */
  1180.  
  1181. #ifdef VMS
  1182. /* Unfortunatelly, the VAX C sbrk() is buggy. For example, it returns
  1183.    memory in 512 byte chunks (not a bug, but there's more), AND it
  1184.    adds an extra 512 byte chunk if you ask for a multiple of 512
  1185.    bytes (you ask for 512 bytes, you get 1024 bytes...). And also,
  1186.    the VAX C sbrk does not handle negative increments...
  1187.    There's a similar problem with brk(). Even if you set the break
  1188.    to an even page boundary, it gives you one extra page... */
  1189.  
  1190. static char vms_brk_info_fetched = -1; /* -1 if this is the first time, otherwise
  1191.                       bit 0 set if 'increment' needs adjustment
  1192.                       bit 1 set if the value to brk() needs adjustment */
  1193. static char *vms_brk_start = 0;
  1194. static char *vms_brk_end = 0;
  1195. static char *vms_brk_current = 0;
  1196. #endif
  1197.  
  1198. /* Allocate INCREMENT more bytes of data space,
  1199.    and return the start of data space, or NULL on errors.
  1200.    If INCREMENT is negative, shrink data space.  */
  1201. __ptr_t
  1202. __default_morecore (increment)
  1203.      ptrdiff_t increment;
  1204. {
  1205.   __ptr_t result;
  1206. #ifdef VMS
  1207.   __ptr_t temp;
  1208.  
  1209. #ifdef RL_DEBUG
  1210.   printf("DEBUG:  morecore: increment = %x\n", increment);
  1211.   printf("        @ start:  vms_brk_info_fetched = %x\n", vms_brk_info_fetched);
  1212.   printf("                  vms_brk_start   = %p\n", vms_brk_start);
  1213.   printf("                  vms_brk_current = %p\n", vms_brk_current);
  1214.   printf("                  vms_brk_end     = %p\n", vms_brk_end);
  1215.   printf("        @ end:    ");
  1216. #endif
  1217.  
  1218.   if (vms_brk_info_fetched < 0)
  1219.     {
  1220.       vms_brk_current = vms_brk_start = __sbrk (512);
  1221.       vms_brk_end = __sbrk (0);
  1222.       if (vms_brk_end - vms_brk_current == 1024)
  1223.     vms_brk_info_fetched = 1;
  1224.       else
  1225.     vms_brk_info_fetched = 0;
  1226.       vms_brk_end = brk(vms_brk_start);
  1227.       if (vms_brk_end != vms_brk_start)
  1228.     vms_brk_info_fetched |= 2;
  1229. #ifdef RL_DEBUG
  1230.       printf("vms_brk_info_fetched = %x\n", vms_brk_info_fetched);
  1231.       printf("                  vms_brk_start   = %p\n", vms_brk_start);
  1232.       printf("                  vms_brk_current = %p\n", vms_brk_current);
  1233.       printf("                  vms_brk_end     = %p\n", vms_brk_end);
  1234.       printf("                  ");
  1235. #endif
  1236.     }
  1237.  
  1238.   if (increment < 0)
  1239.     {
  1240.       printf("BZZZZZT! ERROR: __default_morecore does NOT take negative args\n");
  1241.       return NULL;
  1242.     }
  1243.  
  1244.   if (increment > 0)
  1245.     {
  1246.       result = vms_brk_current;
  1247.       temp = vms_brk_current + increment;
  1248.  
  1249.       if (temp > vms_brk_end)
  1250.     {
  1251.       __ptr_t foo;
  1252.  
  1253.       foo = __sbrk (0);
  1254.       if (foo == vms_brk_end)
  1255.         {
  1256.           increment = temp - vms_brk_end;
  1257.           if (increment > (vms_brk_info_fetched & 1))
  1258.         increment -=  (vms_brk_info_fetched & 1);
  1259.           foo = __sbrk(increment);
  1260. #ifdef RL_DEBUG
  1261.           printf("__sbrk(%d) --> %p\n", increment, foo);
  1262. #endif
  1263.           if (foo == (__ptr_t) -1)
  1264.         return NULL;
  1265. #ifdef RL_DEBUG
  1266.           printf("                  ");
  1267. #endif
  1268.         }
  1269.       else
  1270.         {
  1271.           result = __sbrk (increment);
  1272.  
  1273.           if (result == (__ptr_t) -1)
  1274.         return NULL;
  1275.  
  1276.           temp = result + increment;
  1277.         }
  1278.  
  1279.       vms_brk_end = __sbrk(0);
  1280.     }
  1281.       vms_brk_current = temp;
  1282. #ifdef RL_DEBUG
  1283.       printf("vms_brk_current = %p\n", vms_brk_current);
  1284.       printf("                  vms_brk_end     = %p\n", vms_brk_end);
  1285. #endif
  1286.       return result;
  1287.     }
  1288. #ifdef RL_DEBUG
  1289.   printf(" nothing more...\n");
  1290. #endif
  1291.  
  1292.   /* OK, so the user wanted to check where the heap limit is. Let's
  1293.      see if the system thinks it is where we think it is. */
  1294.   temp = __sbrk (0);
  1295.   if (temp != vms_brk_end)
  1296.     {
  1297.       /* the value has changed.
  1298.      Let's trust the system and modify our value */
  1299.       vms_brk_current = vms_brk_end = temp;
  1300.     }
  1301.   return vms_brk_current;
  1302.  
  1303. #else /* not VMS */
  1304.   result = __sbrk ((int) increment);
  1305.   if (result == (__ptr_t) -1)
  1306.     return NULL;
  1307.   return result;
  1308. #endif /* VMS */
  1309. }
  1310.  
  1311. __ptr_t
  1312. __default_lesscore (ptr, size)
  1313.      __ptr_t ptr;
  1314.      ptrdiff_t size;
  1315. {
  1316. #ifdef VMS
  1317.   if (vms_brk_end != 0)
  1318.     {
  1319.       vms_brk_current = ptr;
  1320.       if (vms_brk_current < vms_brk_start)
  1321.     vms_brk_current = vms_brk_start;
  1322.       vms_brk_end = (char *) vms_brk_current -
  1323.     ((vms_brk_info_fetched >> 1) & 1);
  1324. #ifdef RL_DEBUG
  1325.       printf("<<<bar... %p (%p (%p, %d))...",
  1326.          vms_brk_end, vms_brk_current, ptr, size);
  1327. #endif
  1328.       vms_brk_end = __brk (vms_brk_end);
  1329. #ifdef RL_DEBUG
  1330.       printf("foo... %p.\n", vms_brk_end);
  1331. #endif
  1332.     }
  1333.  
  1334.   return vms_brk_current;
  1335. #else /* not VMS */
  1336.   __default_morecore (-size);
  1337. #endif
  1338. }
  1339.  
  1340. /* Allocate memory on a page boundary.
  1341.    Copyright (C) 1991, 1992 Free Software Foundation, Inc.
  1342.  
  1343. This library is free software; you can redistribute it and/or
  1344. modify it under the terms of the GNU Library General Public License as
  1345. published by the Free Software Foundation; either version 2 of the
  1346. License, or (at your option) any later version.
  1347.  
  1348. This library is distributed in the hope that it will be useful,
  1349. but WITHOUT ANY WARRANTY; without even the implied warranty of
  1350. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  1351. Library General Public License for more details.
  1352.  
  1353. You should have received a copy of the GNU Library General Public
  1354. License along with this library; see the file COPYING.LIB.  If
  1355. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  1356. Cambridge, MA 02139, USA.
  1357.  
  1358.    The author may be reached (Email) at the address mike@ai.mit.edu,
  1359.    or (US mail) as Mike Haertel c/o Free Software Foundation.  */
  1360.  
  1361. #ifndef    _MALLOC_INTERNAL
  1362. #define    _MALLOC_INTERNAL
  1363. #include <malloc.h>
  1364. #endif
  1365.  
  1366. #if defined (emacs) || defined (HAVE_CONFIG_H)
  1367. #include "config.h"
  1368. #endif
  1369.  
  1370. #ifdef    __GNU_LIBRARY__
  1371. extern size_t __getpagesize __P ((void));
  1372. #else
  1373. #if !defined(USG) && !defined(VMS)
  1374. extern size_t getpagesize __P ((void));
  1375. #define    __getpagesize()    getpagesize()
  1376. #else
  1377. #include <sys/param.h>
  1378. #ifdef    EXEC_PAGESIZE
  1379. #define    __getpagesize()    EXEC_PAGESIZE
  1380. #else /* No EXEC_PAGESIZE.  */
  1381. #ifdef    NBPG
  1382. #ifndef    CLSIZE
  1383. #define    CLSIZE    1
  1384. #endif /* No CLSIZE.  */
  1385. #define    __getpagesize()    (NBPG * CLSIZE)
  1386. #else /* No NBPG.  */
  1387. #define    __getpagesize()    NBPC
  1388. #endif /* NBPG.  */
  1389. #endif /* EXEC_PAGESIZE.  */
  1390. #endif /* USG.  */
  1391. #endif
  1392.  
  1393. static size_t pagesize;
  1394.  
  1395. __ptr_t
  1396. valloc (size)
  1397.      size_t size;
  1398. {
  1399.   if (pagesize == 0)
  1400.     pagesize = __getpagesize ();
  1401.  
  1402.   return memalign (pagesize, size);
  1403. }
  1404. /* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
  1405.  
  1406. This library is free software; you can redistribute it and/or
  1407. modify it under the terms of the GNU Library General Public License as
  1408. published by the Free Software Foundation; either version 2 of the
  1409. License, or (at your option) any later version.
  1410.  
  1411. This library is distributed in the hope that it will be useful,
  1412. but WITHOUT ANY WARRANTY; without even the implied warranty of
  1413. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  1414. Library General Public License for more details.
  1415.  
  1416. You should have received a copy of the GNU Library General Public
  1417. License along with this library; see the file COPYING.LIB.  If
  1418. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  1419. Cambridge, MA 02139, USA.  */
  1420.  
  1421. #ifndef    _MALLOC_INTERNAL
  1422. #define _MALLOC_INTERNAL
  1423. #include <malloc.h>
  1424. #endif
  1425.  
  1426. __ptr_t
  1427. memalign (alignment, size)
  1428.      size_t alignment;
  1429.      size_t size;
  1430. {
  1431.   __ptr_t result;
  1432.   unsigned long int adj;
  1433.  
  1434.   size = ((size + alignment - 1) / alignment) * alignment;
  1435.  
  1436.   result = malloc (size);
  1437.   if (result == NULL)
  1438.     return NULL;
  1439.   adj = (unsigned long int) ((unsigned long int) ((char *) result -
  1440.                         (char *) NULL)) % alignment;
  1441.   if (adj != 0)
  1442.     {
  1443.       struct alignlist *l;
  1444.       for (l = _aligned_blocks; l != NULL; l = l->next)
  1445.     if (l->aligned == NULL)
  1446.       /* This slot is free.  Use it.  */
  1447.       break;
  1448.       if (l == NULL)
  1449.     {
  1450.       l = (struct alignlist *) malloc (sizeof (struct alignlist));
  1451.       if (l == NULL)
  1452.         {
  1453.           free (result);
  1454.           return NULL;
  1455.         }
  1456.     }
  1457.       l->exact = result;
  1458.       result = l->aligned = (char *) result + alignment - adj;
  1459.       l->next = _aligned_blocks;
  1460.       _aligned_blocks = l;
  1461.     }
  1462.  
  1463.   return result;
  1464. }
  1465.  
  1466. #ifdef VMS
  1467. struct vms_malloc_data
  1468. {
  1469.   int __malloc_initialized;
  1470.   char *_heapbase;
  1471.   malloc_info *_heapinfo;
  1472.   size_t heapsize;
  1473.   size_t _heapindex;
  1474.   size_t _heaplimit;
  1475.   size_t _chunks_used;
  1476.   size_t _bytes_used;
  1477.   size_t _chunks_free;
  1478.   size_t _bytes_free;
  1479. } ____vms_malloc_data[] =
  1480. {
  1481.   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  1482.   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
  1483. };
  1484.  
  1485. struct vms_core_routines
  1486. {
  1487.   __ptr_t (*__morecore) __P ((ptrdiff_t increment));
  1488.   __ptr_t (*__lesscore) __P ((__ptr_t address, ptrdiff_t increment));
  1489. } ____vms_core_routines[] =
  1490. {
  1491.   { __vms_initial_morecore, __vms_initial_lesscore },
  1492.   { __default_morecore, __default_lesscore },
  1493.   { 0, 0 }
  1494. };
  1495.  
  1496. static int current_vms_data = -1;
  1497. static int current_vms_core_routines = 0;
  1498.  
  1499. static void use_vms_core_routines (int i)
  1500. {
  1501.   current_vms_core_routines = i;
  1502.   current_vms_data = i;
  1503. }
  1504.  
  1505. static void use_vms_data (int i)
  1506. {
  1507.   use_vms_core_routines (i);
  1508.   __malloc_initialized = ____vms_malloc_data[i].__malloc_initialized;
  1509.   _heapbase = ____vms_malloc_data[i]._heapbase;
  1510.   _heapinfo = ____vms_malloc_data[i]._heapinfo;
  1511.   heapsize = ____vms_malloc_data[i].heapsize;
  1512.   _heapindex = ____vms_malloc_data[i]._heapindex;
  1513.   _heaplimit = ____vms_malloc_data[i]._heaplimit;
  1514.   _chunks_used = ____vms_malloc_data[i]._chunks_used;
  1515.   _bytes_used = ____vms_malloc_data[i]._bytes_used;
  1516.   _chunks_free = ____vms_malloc_data[i]._chunks_free;
  1517.   _bytes_free = ____vms_malloc_data[i]._bytes_free;
  1518. }
  1519.   
  1520. static void store_vms_data (int i)
  1521. {
  1522.   ____vms_malloc_data[i].__malloc_initialized = __malloc_initialized;
  1523.   ____vms_malloc_data[i]._heapbase = _heapbase;
  1524.   ____vms_malloc_data[i]._heapinfo = _heapinfo;
  1525.   ____vms_malloc_data[i].heapsize = heapsize;
  1526.   ____vms_malloc_data[i]._heapindex = _heapindex;
  1527.   ____vms_malloc_data[i]._heaplimit = _heaplimit;
  1528.   ____vms_malloc_data[i]._chunks_used = _chunks_used;
  1529.   ____vms_malloc_data[i]._bytes_used = _bytes_used;
  1530.   ____vms_malloc_data[i]._chunks_free = _chunks_free;
  1531.   ____vms_malloc_data[i]._bytes_free = _bytes_free;
  1532. }
  1533.  
  1534. static void store_current_vms_data ()
  1535. {
  1536.   switch (current_vms_data)
  1537.     {
  1538.     case 0:
  1539.     case 1:
  1540.       store_vms_data (current_vms_data);
  1541.       break;
  1542.     }
  1543. }
  1544.  
  1545. __ptr_t __vms_morecore (increment)
  1546.      ptrdiff_t increment;
  1547. {
  1548.   return
  1549.     (*____vms_core_routines[current_vms_core_routines].__morecore) (increment);
  1550. }
  1551.  
  1552. __ptr_t __vms_lesscore (ptr, increment)
  1553.      __ptr_t ptr;
  1554.      ptrdiff_t increment;
  1555. {
  1556.   return
  1557.     (*____vms_core_routines[current_vms_core_routines].__lesscore) (ptr,increment);
  1558. }
  1559.  
  1560. __ptr_t __vms_malloc (size)
  1561.      size_t size;
  1562. {
  1563.   __ptr_t result;
  1564.   int old_current_vms_data = current_vms_data;
  1565.  
  1566.   __malloc_hook = 0;
  1567.  
  1568.   store_current_vms_data ();
  1569.  
  1570.   if (____vms_malloc_data[0]._heapbase != 0)
  1571.     use_vms_data (0);
  1572.   else
  1573.     use_vms_core_routines (0);
  1574.   result = malloc (size);
  1575.   store_vms_data (0);
  1576.   if (result == NULL)
  1577.     {
  1578.       use_vms_data (1);
  1579.       result = malloc (size);
  1580.       store_vms_data (1);
  1581.       vms_out_initial = 1;
  1582.     }
  1583.   __malloc_hook = __vms_malloc;
  1584.   if (old_current_vms_data != -1)
  1585.     use_vms_data (current_vms_data);
  1586.   return result;
  1587. }
  1588.  
  1589. void __vms_free (ptr)
  1590.      __ptr_t ptr;
  1591. {
  1592.   int old_current_vms_data = current_vms_data;
  1593.  
  1594.   __free_hook = 0;
  1595.  
  1596.   store_current_vms_data ();
  1597.  
  1598.   if (ptr >= vms_initial_buffer && ptr <= vms_end_brk)
  1599.     {
  1600.       use_vms_data (0);
  1601.       free (ptr);
  1602.       store_vms_data (0);
  1603.     }
  1604.   else
  1605.     {
  1606.       use_vms_data (1);
  1607.       free (ptr);
  1608.       store_vms_data (1);
  1609.       if (_chunks_free == 0 && _chunks_used == 0)
  1610.     vms_out_initial = 0;
  1611.     }
  1612.   __free_hook = __vms_free;
  1613.   if (old_current_vms_data != -1)
  1614.     use_vms_data (current_vms_data);
  1615. }
  1616.  
  1617. __ptr_t __vms_realloc (ptr, size)
  1618.      __ptr_t ptr;
  1619.      size_t size;
  1620. {
  1621.   __ptr_t result;
  1622.   int old_current_vms_data = current_vms_data;
  1623.  
  1624.   __realloc_hook = 0;
  1625.  
  1626.   store_current_vms_data ();
  1627.  
  1628.   if (ptr >= vms_initial_buffer && ptr <= vms_end_brk)
  1629.     {
  1630.       use_vms_data (0);
  1631.       result = realloc (ptr, size);
  1632.       store_vms_data (0);
  1633.     }
  1634.   else
  1635.     {
  1636.       use_vms_data (1);
  1637.       result = realloc (ptr, size);
  1638.       store_vms_data (1);
  1639.     }
  1640.   __realloc_hook = __vms_realloc;
  1641.   if (old_current_vms_data != -1)
  1642.     use_vms_data (current_vms_data);
  1643.   return result;
  1644. }  
  1645. #endif /* VMS */
  1646. /* Standard debugging hooks for `malloc'.
  1647.    Copyright 1990, 1991, 1992 Free Software Foundation
  1648.    Written May 1989 by Mike Haertel.
  1649.  
  1650. This library is free software; you can redistribute it and/or
  1651. modify it under the terms of the GNU Library General Public License as
  1652. published by the Free Software Foundation; either version 2 of the
  1653. License, or (at your option) any later version.
  1654.  
  1655. This library is distributed in the hope that it will be useful,
  1656. but WITHOUT ANY WARRANTY; without even the implied warranty of
  1657. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  1658. Library General Public License for more details.
  1659.  
  1660. You should have received a copy of the GNU Library General Public
  1661. License along with this library; see the file COPYING.LIB.  If
  1662. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  1663. Cambridge, MA 02139, USA.
  1664.  
  1665.    The author may be reached (Email) at the address mike@ai.mit.edu,
  1666.    or (US mail) as Mike Haertel c/o Free Software Foundation.  */
  1667.  
  1668. #ifndef    _MALLOC_INTERNAL
  1669. #define    _MALLOC_INTERNAL
  1670. #include <malloc.h>
  1671. #endif
  1672.  
  1673. /* Old hook values.  */
  1674. static void (*old_free_hook) __P ((__ptr_t ptr));
  1675. static __ptr_t (*old_malloc_hook) __P ((size_t size));
  1676. static __ptr_t (*old_realloc_hook) __P ((__ptr_t ptr, size_t size));
  1677.  
  1678. /* Function to call when something awful happens.  */
  1679. static void (*abortfunc) __P ((void));
  1680.  
  1681. /* Arbitrary magical numbers.  */
  1682. #define MAGICWORD    0xfedabeeb
  1683. #define MAGICBYTE    ((char) 0xd7)
  1684.  
  1685. struct hdr
  1686.   {
  1687.     size_t size;        /* Exact size requested by user.  */
  1688.     unsigned long int magic;    /* Magic number to check header integrity.  */
  1689.   };
  1690.  
  1691. static void checkhdr __P ((__const struct hdr *));
  1692. static void
  1693. checkhdr (hdr)
  1694.      __const struct hdr *hdr;
  1695. {
  1696.   if (hdr->magic != MAGICWORD || ((char *) &hdr[1])[hdr->size] != MAGICBYTE)
  1697.     (*abortfunc) ();
  1698. }
  1699.  
  1700. static void freehook __P ((__ptr_t));
  1701. static void
  1702. freehook (ptr)
  1703.      __ptr_t ptr;
  1704. {
  1705.   struct hdr *hdr = ((struct hdr *) ptr) - 1;
  1706.   checkhdr (hdr);
  1707.   hdr->magic = 0;
  1708.   __free_hook = old_free_hook;
  1709.   free (hdr);
  1710.   __free_hook = freehook;
  1711. }
  1712.  
  1713. static __ptr_t mallochook __P ((size_t));
  1714. static __ptr_t
  1715. mallochook (size)
  1716.      size_t size;
  1717. {
  1718.   struct hdr *hdr;
  1719.  
  1720.   __malloc_hook = old_malloc_hook;
  1721.   hdr = (struct hdr *) malloc (sizeof (struct hdr) + size + 1);
  1722.   __malloc_hook = mallochook;
  1723.   if (hdr == NULL)
  1724.     return NULL;
  1725.  
  1726.   hdr->size = size;
  1727.   hdr->magic = MAGICWORD;
  1728.   ((char *) &hdr[1])[size] = MAGICBYTE;
  1729.   return (__ptr_t) (hdr + 1);
  1730. }
  1731.  
  1732. static __ptr_t reallochook __P ((__ptr_t, size_t));
  1733. static __ptr_t
  1734. reallochook (ptr, size)
  1735.      __ptr_t ptr;
  1736.      size_t size;
  1737. {
  1738.   struct hdr *hdr = ((struct hdr *) ptr) - 1;
  1739.  
  1740.   checkhdr (hdr);
  1741.   __free_hook = old_free_hook;
  1742.   __malloc_hook = old_malloc_hook;
  1743.   __realloc_hook = old_realloc_hook;
  1744.   hdr = (struct hdr *) realloc ((__ptr_t) hdr, sizeof (struct hdr) + size + 1);
  1745.   __free_hook = freehook;
  1746.   __malloc_hook = mallochook;
  1747.   __realloc_hook = reallochook;
  1748.   if (hdr == NULL)
  1749.     return NULL;
  1750.  
  1751.   hdr->size = size;
  1752.   ((char *) &hdr[1])[size] = MAGICBYTE;
  1753.   return (__ptr_t) (hdr + 1);
  1754. }
  1755.  
  1756. int
  1757. mcheck (func)
  1758.      void (*func) __P ((void));
  1759. {
  1760.   extern void abort __P ((void));
  1761.   static int mcheck_used = 0;
  1762.  
  1763.   abortfunc = (func != NULL) ? func : abort;
  1764.  
  1765.   /* These hooks may not be safely inserted if malloc is already in use.  */
  1766.   if (!__malloc_initialized && !mcheck_used)
  1767.     {
  1768.       old_free_hook = __free_hook;
  1769.       __free_hook = freehook;
  1770.       old_malloc_hook = __malloc_hook;
  1771.       __malloc_hook = mallochook;
  1772.       old_realloc_hook = __realloc_hook;
  1773.       __realloc_hook = reallochook;
  1774.       mcheck_used = 1;
  1775.     }
  1776.  
  1777.   return mcheck_used ? 0 : -1;
  1778. }
  1779. /* More debugging hooks for `malloc'.
  1780.    Copyright (C) 1991, 1992 Free Software Foundation, Inc.
  1781.          Written April 2, 1991 by John Gilmore of Cygnus Support.
  1782.          Based on mcheck.c by Mike Haertel.
  1783.  
  1784. This library is free software; you can redistribute it and/or
  1785. modify it under the terms of the GNU Library General Public License as
  1786. published by the Free Software Foundation; either version 2 of the
  1787. License, or (at your option) any later version.
  1788.  
  1789. This library is distributed in the hope that it will be useful,
  1790. but WITHOUT ANY WARRANTY; without even the implied warranty of
  1791. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  1792. Library General Public License for more details.
  1793.  
  1794. You should have received a copy of the GNU Library General Public
  1795. License along with this library; see the file COPYING.LIB.  If
  1796. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  1797. Cambridge, MA 02139, USA.
  1798.  
  1799.    The author may be reached (Email) at the address mike@ai.mit.edu,
  1800.    or (US mail) as Mike Haertel c/o Free Software Foundation.  */
  1801.  
  1802. #ifndef    _MALLOC_INTERNAL
  1803. #define    _MALLOC_INTERNAL
  1804. #include <malloc.h>
  1805. #endif
  1806.  
  1807. #include <stdio.h>
  1808.  
  1809. #ifndef    __GNU_LIBRARY__
  1810. extern char *getenv ();
  1811. #else
  1812. #include <stdlib.h>
  1813. #endif
  1814.  
  1815. static FILE *mallstream;
  1816. static char mallenv[]= "MALLOC_TRACE";
  1817. static char mallbuf[BUFSIZ];    /* Buffer for the output.  */
  1818.  
  1819. /* Address to breakpoint on accesses to... */
  1820. __ptr_t mallwatch;
  1821.  
  1822. /* Old hook values.  */
  1823. static __ptr_t (*tr_old_morecore) __P ((ptrdiff_t increment));
  1824. static __ptr_t (*tr_old_lesscore) __P ((__ptr_t ptr, ptrdiff_t increment));
  1825. static void (*tr_old_free_hook) __P ((__ptr_t ptr));
  1826. static __ptr_t (*tr_old_malloc_hook) __P ((size_t size));
  1827. static __ptr_t (*tr_old_realloc_hook) __P ((__ptr_t ptr, size_t size));
  1828.  
  1829. /* This function is called when the block being alloc'd, realloc'd, or
  1830.    freed has an address matching the variable "mallwatch".  In a debugger,
  1831.    set "mallwatch" to the address of interest, then put a breakpoint on
  1832.    tr_break.  */
  1833.  
  1834. void tr_break __P ((void));
  1835. void
  1836. tr_break ()
  1837. {
  1838. }
  1839.  
  1840. static void tr_freehook __P ((__ptr_t));
  1841. static void
  1842. tr_freehook (ptr)
  1843.      __ptr_t ptr;
  1844. {
  1845.   fprintf (mallstream, "- %p\n", ptr);    /* Be sure to print it first.  */
  1846.   if (ptr == mallwatch)
  1847.     tr_break ();
  1848.   __free_hook = tr_old_free_hook;
  1849.   free (ptr);
  1850.   __free_hook = tr_freehook;
  1851. }
  1852.  
  1853. static __ptr_t tr_morecore __P ((ptrdiff_t));
  1854. static __ptr_t
  1855. tr_morecore (increment)
  1856.      ptrdiff_t increment;
  1857. {
  1858.   __ptr_t p;
  1859.  
  1860.   __morecore = tr_old_morecore;
  1861.   p = (__ptr_t) (*__morecore) (increment);
  1862.   __morecore = tr_morecore;
  1863.  
  1864.   fprintf (mallstream, "$ %p %d\n", p, increment);
  1865.  
  1866.   return p;
  1867. }
  1868.  
  1869. static __ptr_t tr_lesscore __P ((__ptr_t, ptrdiff_t));
  1870. static __ptr_t
  1871. tr_lesscore (ptr, increment)
  1872.      __ptr_t ptr;
  1873.      ptrdiff_t increment;
  1874. {
  1875.   __ptr_t p;
  1876.  
  1877.   __lesscore = tr_old_lesscore;
  1878.   p = (__ptr_t) (*__lesscore) (ptr, increment);
  1879.   __lesscore = tr_lesscore;
  1880.  
  1881.   fprintf (mallstream, "* %p (%p, %d)\n", p, ptr, increment);
  1882.  
  1883.   return p;
  1884. }
  1885.  
  1886. static __ptr_t tr_mallochook __P ((size_t));
  1887. static __ptr_t
  1888. tr_mallochook (size)
  1889.      size_t size;
  1890. {
  1891.   __ptr_t hdr;
  1892.  
  1893.   __malloc_hook = tr_old_malloc_hook;
  1894.   hdr = (__ptr_t) malloc (size);
  1895.   __malloc_hook = tr_mallochook;
  1896.  
  1897.   /* We could be printing a NULL here; that's OK.  */
  1898.   fprintf (mallstream, "+ %p %x\n", hdr, size);
  1899.  
  1900.   if (hdr == mallwatch)
  1901.     tr_break ();
  1902.  
  1903.   return hdr;
  1904. }
  1905.  
  1906. static __ptr_t tr_reallochook __P ((__ptr_t, size_t));
  1907. static __ptr_t
  1908. tr_reallochook (ptr, size)
  1909.      __ptr_t ptr;
  1910.      size_t size;
  1911. {
  1912.   __ptr_t hdr;
  1913.  
  1914.   if (ptr == mallwatch)
  1915.     tr_break ();
  1916.  
  1917.   __free_hook = tr_old_free_hook;
  1918.   __malloc_hook = tr_old_malloc_hook;
  1919.   __realloc_hook = tr_old_realloc_hook;
  1920.   hdr = (__ptr_t) realloc (ptr, size);
  1921.   __free_hook = tr_freehook;
  1922.   __malloc_hook = tr_mallochook;
  1923.   __realloc_hook = tr_reallochook;
  1924.   if (hdr == NULL)
  1925.     /* Failed realloc.  */
  1926.     fprintf (mallstream, "! %p %x\n", ptr, size);
  1927.   else
  1928.     fprintf (mallstream, "< %p\n> %p %x\n", ptr, hdr, size);
  1929.  
  1930.   if (hdr == mallwatch)
  1931.     tr_break ();
  1932.  
  1933.   return hdr;
  1934. }
  1935.  
  1936. /* We enable tracing if either the environment variable MALLOC_TRACE
  1937.    is set, or if the variable mallwatch has been patched to an address
  1938.    that the debugging user wants us to stop on.  When patching mallwatch,
  1939.    don't forget to set a breakpoint on tr_break!  */
  1940.  
  1941. void
  1942. mtrace ()
  1943. {
  1944.   char *mallfile;
  1945.  
  1946.   mallfile = getenv (mallenv);
  1947.   if (mallfile != NULL || mallwatch != NULL)
  1948.     {
  1949.       mallstream = fopen (mallfile != NULL ? mallfile : "/dev/null", "w");
  1950.       if (mallstream != NULL)
  1951.     {
  1952.       /* Be sure it doesn't malloc its buffer!  */
  1953.       setbuf (mallstream, mallbuf);
  1954.       fprintf (mallstream, "= Start\n");
  1955. #if defined(emacs) && defined(VMS)
  1956.       fprintf (mallstream, "= Initial buffer spans %p -- %p\n",
  1957.            vms_initial_buffer, vms_end_brk + 1);
  1958. #endif
  1959.       tr_old_morecore = __morecore;
  1960.       __morecore = tr_morecore;
  1961.       tr_old_lesscore = __lesscore;
  1962.       __lesscore = tr_lesscore;
  1963.       tr_old_free_hook = __free_hook;
  1964.       __free_hook = tr_freehook;
  1965.       tr_old_malloc_hook = __malloc_hook;
  1966.       __malloc_hook = tr_mallochook;
  1967.       tr_old_realloc_hook = __realloc_hook;
  1968.       __realloc_hook = tr_reallochook;
  1969.     }
  1970.     }
  1971. }
  1972. /* Access the statistics maintained by `malloc'.
  1973.    Copyright 1990, 1991, 1992 Free Software Foundation
  1974.           Written May 1989 by Mike Haertel.
  1975.  
  1976. This library is free software; you can redistribute it and/or
  1977. modify it under the terms of the GNU Library General Public License as
  1978. published by the Free Software Foundation; either version 2 of the
  1979. License, or (at your option) any later version.
  1980.  
  1981. This library is distributed in the hope that it will be useful,
  1982. but WITHOUT ANY WARRANTY; without even the implied warranty of
  1983. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  1984. Library General Public License for more details.
  1985.  
  1986. You should have received a copy of the GNU Library General Public
  1987. License along with this library; see the file COPYING.LIB.  If
  1988. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  1989. Cambridge, MA 02139, USA.
  1990.  
  1991.    The author may be reached (Email) at the address mike@ai.mit.edu,
  1992.    or (US mail) as Mike Haertel c/o Free Software Foundation.  */
  1993.  
  1994. #ifndef    _MALLOC_INTERNAL
  1995. #define _MALLOC_INTERNAL
  1996. #include <malloc.h>
  1997. #endif
  1998.  
  1999. struct mstats
  2000. mstats ()
  2001. {
  2002.   struct mstats result;
  2003.  
  2004.   result.bytes_total = (char *) (*__morecore) (0) - _heapbase;
  2005.   result.chunks_used = _chunks_used;
  2006.   result.bytes_used = _bytes_used;
  2007.   result.chunks_free = _chunks_free;
  2008.   result.bytes_free = _bytes_free;
  2009.   return result;
  2010. }
  2011.